﻿#include "InstructionSet.h"
#include <commctrl.h>

#pragma comment(lib, "Imm32.lib")
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

std::vector<ASM_6502_INFO> g_6502_set = {
    ASM_6502_INFO(_T("ADC ($addr,X)"),  _T("61"), _T("先变址X后间址"),      _T("6"), _T("NVbdiZC"), _T("累加器，存储器，进位标志C相加，结果送累加器A\r\nA + M + C → A")),
    ASM_6502_INFO(_T("ADC $addr"),      _T("65"), _T("零页寻址"),           _T("3"), _T("NVbdiZC"), _T("累加器，存储器，进位标志C相加，结果送累加器A\r\nA + M + C → A")),
    ASM_6502_INFO(_T("ADC #$data"),     _T("69"), _T("立即寻址"),           _T("2"), _T("NVbdiZC"), _T("累加器，存储器，进位标志C相加，结果送累加器A\r\nA + M + C → A")),
    ASM_6502_INFO(_T("ADC $addr16"),    _T("6D"), _T("绝对寻址"),           _T("4"), _T("NVbdiZC"), _T("累加器，存储器，进位标志C相加，结果送累加器A\r\nA + M + C → A")),
    ASM_6502_INFO(_T("ADC ($addr),Y"),  _T("71"), _T("后变址Y间址"),        _T("5"), _T("NVbdiZC"), _T("累加器，存储器，进位标志C相加，结果送累加器A\r\nA + M + C → A")),
    ASM_6502_INFO(_T("ADC $addr,X"),    _T("75"), _T("零页X变址"),          _T("4"), _T("NVbdiZC"), _T("累加器，存储器，进位标志C相加，结果送累加器A\r\nA + M + C → A")),
    ASM_6502_INFO(_T("ADC $addr16,Y"),  _T("79"), _T("绝对Y变址"),          _T("4\r\n(跳转到另一页时 +1)"), _T("NVbdiZC"), _T("累加器，存储器，进位标志C相加，结果送累加器A\r\nA + M + C → A")),
    ASM_6502_INFO(_T("ADC $addr16,X"),  _T("7D"), _T("绝对X变址"),          _T("4\r\n(跳转到另一页时 +1)"), _T("NVbdiZC"), _T("累加器，存储器，进位标志C相加，结果送累加器A\r\nA + M + C → A")),
    ASM_6502_INFO(_T("AND ($addr,X)"),  _T("21"), _T("先变址X后间址"),      _T("6"), _T("NvbdiZc"), _T("寄存器与累加器相与，结果送累加器\r\nA ∧ M → A")),
    ASM_6502_INFO(_T("AND $addr"),      _T("25"), _T("零页寻址"),           _T("3"), _T("NvbdiZc"), _T("寄存器与累加器相与，结果送累加器\r\nA ∧ M → A")),
    ASM_6502_INFO(_T("AND #$data"),     _T("29"), _T("立即寻址"),           _T("2"), _T("NvbdiZc"), _T("寄存器与累加器相与，结果送累加器\r\nA ∧ M → A")),
    ASM_6502_INFO(_T("AND $addr16"),    _T("2D"), _T("绝对寻址"),           _T("4"), _T("NvbdiZc"), _T("寄存器与累加器相与，结果送累加器\r\nA ∧ M → A")),
    ASM_6502_INFO(_T("AND ($addr),Y"),  _T("31"), _T("后变址Y间址"),        _T("5\r\n(跳转到另一页时 +1)"), _T("NvbdiZc"), _T("寄存器与累加器相与，结果送累加器\r\nA ∧ M → A")),
    ASM_6502_INFO(_T("AND $addr,X"),    _T("35"), _T("零页X变址"),          _T("4"), _T("NvbdiZc"), _T("寄存器与累加器相与，结果送累加器\r\nA ∧ M → A")),
    ASM_6502_INFO(_T("AND $addr16,Y"),  _T("39"), _T("绝对Y变址"),          _T("4\r\n(跳转到另一页时 +1)"), _T("NvbdiZc"), _T("寄存器与累加器相与，结果送累加器\r\nA ∧ M → A")),
    ASM_6502_INFO(_T("AND $addr16,X"),  _T("3D"), _T("绝对X变址"),          _T("4\r\n(跳转到另一页时 +1)"), _T("NvbdiZc"), _T("寄存器与累加器相与，结果送累加器\r\nA ∧ M → A")),
    ASM_6502_INFO(_T("ASL"),            _T("0A"), _T("累加器寻址"),         _T("2"), _T("NvbdiZC"), _T("算术左移指令，移位功能是将字节内各位依次向左移1位，\r\n最高位移进标志位C中，最底位补0，执行结果相当于把移位前的数乘2")),
    ASM_6502_INFO(_T("ASL $data"),      _T("06"), _T("零页寻址"),           _T("5"), _T("NvbdiZC"), _T("算术左移指令，移位功能是将字节内各位依次向左移1位，\r\n最高位移进标志位C中，最底位补0，执行结果相当于把移位前的数乘2")),
    ASM_6502_INFO(_T("ASL $addr16"),    _T("0E"), _T("绝对寻址"),           _T("6"), _T("NvbdiZC"), _T("算术左移指令，移位功能是将字节内各位依次向左移1位，\r\n最高位移进标志位C中，最底位补0，执行结果相当于把移位前的数乘2")),
    ASM_6502_INFO(_T("ASL $addr,X"),    _T("16"), _T("零页X变址"),          _T("6"), _T("NvbdiZC"), _T("算术左移指令，移位功能是将字节内各位依次向左移1位，\r\n最高位移进标志位C中，最底位补0，执行结果相当于把移位前的数乘2")),
    ASM_6502_INFO(_T("ASL $addr16,X"),  _T("1E"), _T("绝对X变址"),          _T("7"), _T("NvbdiZC"), _T("算术左移指令，移位功能是将字节内各位依次向左移1位，\r\n最高位移进标志位C中，最底位补0，执行结果相当于把移位前的数乘2")),
    ASM_6502_INFO(_T("BCC label"),      _T("90"), _T("相对寻址"),           _T("2\r\n(若 C＝0 而分支跳越时 +1)\r\n(若跳越到另一页区时 +2)"), _T("无影响"), _T("如果标志位 C=0 则转移，否则继续")),
    ASM_6502_INFO(_T("BCS label"),      _T("B0"), _T("相对寻址"),           _T("2\r\n(若 C＝1 而分支跳越时 +1)\r\n(若跳越至另一页区时 +2)"), _T("无影响"), _T("如果标志位 C=1 则转移，否则继续")),
    ASM_6502_INFO(_T("BEQ label"),      _T("F0"), _T("相对寻址"),           _T("2\r\n(若 Z＝1 而分支跳越时 +1)\r\n(若跳越至另一页区时 +2)"), _T("无影响"), _T("如果标志位 Z=1 则转移，否则继续")),
    ASM_6502_INFO(_T("BIT $addr"),      _T("24"), _T("零页寻址"),           _T("3"), _T("NVbdiZc"), _T("位测试指令")),
    ASM_6502_INFO(_T("BIT $addr16"),    _T("2C"), _T("绝对寻址"),           _T("4"), _T("NVbdiZc"), _T("位测试指令")),
    ASM_6502_INFO(_T("BMI label"),      _T("30"), _T("相对寻址"),           _T("2\r\n(若 N＝1 而分支跳越时 +1)\r\n(若跳越至另一页区时 +2)"), _T("无影响"), _T("如果标志位 N=1 则转移，否则继续")),
    ASM_6502_INFO(_T("BNE label"),      _T("D0"), _T("相对寻址"),           _T("2\r\n(若 Z＝0 而分支跳越时 +1)\r\n(若跳越至另一页区时 +2)"), _T("无影响"), _T("如果标志位 Z=0 则转移，否则继续")),
    ASM_6502_INFO(_T("BPL label"),      _T("10"), _T("相对寻址"),           _T("2\r\n(若 N＝0 而分支跳越时 +1)\r\n(若跳越至另一页区时 +2)"), _T("无影响"), _T("如果标志位 N=0 则转移，否则继续")),
    ASM_6502_INFO(_T("BRK"),            _T("00"), _T("隐含寻址"),           _T("7"), _T("nvBdizc"), _T("中断指令")),
    ASM_6502_INFO(_T("BVC label"),      _T("50"), _T("相对寻址"),           _T("2\r\n(若 V＝0 而分支跳越时 +1)\r\n(若跳越至另一页区时 +2)"), _T("无影响"), _T("如果标志位 V=0 则转移，否则继续")),
    ASM_6502_INFO(_T("BVS label"),      _T("70"), _T("相对寻址"),           _T("2\r\n(若 V＝1 而分支跳越时 +1)\r\n(若跳越至另一页区时 +2)"), _T("无影响"), _T("如果标志位 V=1 则转移，否则继续")),
    ASM_6502_INFO(_T("CLC"),            _T("18"), _T("隐含寻址"),           _T("2"), _T("nvbdizC (C=0)"), _T("清除进位标志\r\n0 → C")),
    ASM_6502_INFO(_T("CLD"),            _T("D8"), _T("隐含寻址"),           _T("2"), _T("nvbDizc (D=0)"), _T("清除十进制运算标志D\r\n0 → D")),
    ASM_6502_INFO(_T("CLI"),            _T("58"), _T("隐含寻址"),           _T("2"), _T("nvbdIzc (I=0)"), _T("清除中断禁止指令I\r\n0 → I")),
    ASM_6502_INFO(_T("CLV"),            _T("B8"), _T("隐含寻址"),           _T("2"), _T("nVbdizc (V=0)"), _T("清除溢出标志V\r\n0 → V")),
    ASM_6502_INFO(_T("CMP ($addr,X)"),  _T("C1"), _T("先变址X后间址"),      _T("6"), _T("NvbdiZC"), _T("累加器和存储器比较")),
    ASM_6502_INFO(_T("CMP $addr"),      _T("C5"), _T("零页寻址"),           _T("3"), _T("NvbdiZC"), _T("累加器和存储器比较")),
    ASM_6502_INFO(_T("CMP #$data"),     _T("C9"), _T("立即寻址"),           _T("2"), _T("NvbdiZC"), _T("累加器和存储器比较")),
    ASM_6502_INFO(_T("CMP $addr16"),    _T("CD"), _T("绝对寻址"),           _T("4"), _T("NvbdiZC"), _T("累加器和存储器比较")),
    ASM_6502_INFO(_T("CMP ($addr),Y"),  _T("D1"), _T("后变址Y间址"),        _T("5\r\n(跳转到另一页时 +1)"), _T("NvbdiZC"), _T("累加器和存储器比较")),
    ASM_6502_INFO(_T("CMP $addr,X"),    _T("D5"), _T("零页X变址"),          _T("4"), _T("NvbdiZC"), _T("累加器和存储器比较")),
    ASM_6502_INFO(_T("CMP $addr16,Y"),  _T("D9"), _T("绝对Y变址"),          _T("4\r\n(跳转到另一页时 +1)"), _T("NvbdiZC"), _T("累加器和存储器比较")),
    ASM_6502_INFO(_T("CMP $addr16,X"),  _T("DD"), _T("绝对X变址"),          _T("4\r\n(跳转到另一页时 +1)"), _T("NvbdiZC"), _T("累加器和存储器比较")),
    ASM_6502_INFO(_T("CPX #$data"),     _T("E0"), _T("立即寻址"),           _T("2"), _T("NvbdiZC"), _T("寄存器X的内容和存储器比较")),
    ASM_6502_INFO(_T("CPX $addr"),      _T("E4"), _T("零页寻址"),           _T("3"), _T("NvbdiZC"), _T("寄存器X的内容和存储器比较")),
    ASM_6502_INFO(_T("CPX $addr16"),    _T("EC"), _T("绝对寻址"),           _T("4"), _T("NvbdiZC"), _T("寄存器X的内容和存储器比较")),
    ASM_6502_INFO(_T("CPY #$data"),     _T("C0"), _T("立即寻址"),           _T("2"), _T("NvbdiZC"), _T("寄存器Y的内容和存储器比较")),
    ASM_6502_INFO(_T("CPY $addr"),      _T("C4"), _T("零页寻址"),           _T("3"), _T("NvbdiZC"), _T("寄存器Y的内容和存储器比较")),
    ASM_6502_INFO(_T("CPY $addr16"),    _T("CC"), _T("绝对寻址"),           _T("4"), _T("NvbdiZC"), _T("寄存器Y的内容和存储器比较")),
    ASM_6502_INFO(_T("DEC $addr"),      _T("C6"), _T("零页寻址"),           _T("5"), _T("NvbdiZc"), _T("A存储器单元内容减1\r\nM - 1 → M")),
    ASM_6502_INFO(_T("DEC $addr16"),    _T("CE"), _T("绝对寻址"),           _T("6"), _T("NvbdiZc"), _T("A存储器单元内容减1\r\nM - 1 → M")),
    ASM_6502_INFO(_T("DEC $addr,X"),    _T("D6"), _T("零页X变址"),          _T("6"), _T("NvbdiZc"), _T("A存储器单元内容减1\r\nM - 1 → M")),
    ASM_6502_INFO(_T("DEC $addr16,X"),  _T("DE"), _T("绝对X变址"),          _T("7"), _T("NvbdiZc"), _T("A存储器单元内容减1\r\nM - 1 → M")),
    ASM_6502_INFO(_T("DEX"),            _T("CA"), _T("隐含寻址"),           _T("2"), _T("NvbdiZc"), _T("X存储器单元内容减1\r\nX - 1 → X")),
    ASM_6502_INFO(_T("DEY"),            _T("88"), _T("隐含寻址"),           _T("2"), _T("NvbdiZc"), _T("Y存储器单元内容减1\r\nY - 1 → Y")),
    ASM_6502_INFO(_T("EOR ($addr,X)"),  _T("41"), _T("先变址X后间址"),      _T("6"), _T("NvbdiZc"), _T("寄存器与累加器相异或，结果送累加器\r\nA xor M → A")),
    ASM_6502_INFO(_T("EOR $addr"),      _T("45"), _T("零页寻址"),           _T("3"), _T("NvbdiZc"), _T("寄存器与累加器相异或，结果送累加器\r\nA xor M → A")),
    ASM_6502_INFO(_T("EOR #$data"),     _T("49"), _T("立即寻址"),           _T("2"), _T("NvbdiZc"), _T("寄存器与累加器相异或，结果送累加器\r\nA xor M → A")),
    ASM_6502_INFO(_T("EOR $addr16"),    _T("4D"), _T("绝对寻址"),           _T("4"), _T("NvbdiZc"), _T("寄存器与累加器相异或，结果送累加器\r\nA xor M → A")),
    ASM_6502_INFO(_T("EOR ($addr),Y"),  _T("51"), _T("后变址Y间址"),        _T("5\r\n(跳转到另一页时 +1)"), _T("NvbdiZc"), _T("寄存器与累加器相异或，结果送累加器\r\nA xor M → A")),
    ASM_6502_INFO(_T("EOR $addr,X"),    _T("55"), _T("零页X变址"),          _T("4"), _T("NvbdiZc"), _T("寄存器与累加器相异或，结果送累加器\r\nA xor M → A")),
    ASM_6502_INFO(_T("EOR $addr16,Y"),  _T("59"), _T("绝对Y变址"),          _T("4\r\n(跳转到另一页时 +1)"), _T("NvbdiZc"), _T("寄存器与累加器相异或，结果送累加器\r\nA xor M → A")),
    ASM_6502_INFO(_T("EOR $addr16,X"),  _T("5D"), _T("绝对X变址"),          _T("4\r\n(跳转到另一页时 +1)"), _T("NvbdiZc"), _T("寄存器与累加器相异或，结果送累加器\r\nA xor M → A")),
    ASM_6502_INFO(_T("INC $addr"),      _T("E6"), _T("零页寻址"),           _T("5"), _T("NvbdiZc"), _T("A存储器单元内容增1\r\nM + 1 → M")),
    ASM_6502_INFO(_T("INC $addr16"),    _T("EE"), _T("绝对寻址"),           _T("6"), _T("NvbdiZc"), _T("A存储器单元内容增1\r\nM + 1 → M")),
    ASM_6502_INFO(_T("INC $addr,X"),    _T("F6"), _T("零页X变址"),          _T("6"), _T("NvbdiZc"), _T("A存储器单元内容增1\r\nM + 1 → M")),
    ASM_6502_INFO(_T("INC $addr16,X"),  _T("FE"), _T("绝对X变址"),          _T("7"), _T("NvbdiZc"), _T("A存储器单元内容增1\r\nM + 1 → M")),
    ASM_6502_INFO(_T("INX"),            _T("E8"), _T("隐含寻址"),           _T("2"), _T("NvbdiZc"), _T("X存储器单元内容增1\r\nX + 1 → X")),
    ASM_6502_INFO(_T("INY"),            _T("C8"), _T("隐含寻址"),           _T("2"), _T("NvbdiZc"), _T("Y存储器单元内容增1\r\nY + 1 → Y")),
    ASM_6502_INFO(_T("JMP  $addr16"),   _T("4C"), _T("绝对寻址"),           _T("3"), _T("无影响"), _T("无条件转移指令")),
    ASM_6502_INFO(_T("JMP ($addr16)"),  _T("6C"), _T("间接寻址"),           _T("5"), _T("无影响"), _T("无条件转移指令")),
    ASM_6502_INFO(_T("JSR $addr16"),    _T("20"), _T("绝对寻址"),           _T("6"), _T("无影响"), _T("转移到子程序指令")),
    ASM_6502_INFO(_T("LDA ($addr,X)"),  _T("A1"), _T("先变址X后间址"),      _T("6"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → A")),
    ASM_6502_INFO(_T("LDA $addr"),      _T("A5"), _T("零页寻址"),           _T("3"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → A")),
    ASM_6502_INFO(_T("LDA #$data"),     _T("A9"), _T("立即寻址"),           _T("2"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → A")),
    ASM_6502_INFO(_T("LDA $addr16"),    _T("AD"), _T("绝对寻址"),           _T("4"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → A")),
    ASM_6502_INFO(_T("LDA ($addr),Y"),  _T("B1"), _T("后变址Y间址"),        _T("5\r\n(跳转到另一页时 +1)"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → A")),
    ASM_6502_INFO(_T("LDA $addr,X"),    _T("B5"), _T("零页X变址"),          _T("4"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → A")),
    ASM_6502_INFO(_T("LDA $addr16,Y"),  _T("B9"), _T("绝对Y变址"),          _T("4\r\n(跳转到另一页时 +1)"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → A")),
    ASM_6502_INFO(_T("LDA $addr16,X"),  _T("BD"), _T("绝对X变址"),          _T("4\r\n(跳转到另一页时 +1)"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → A")),
    ASM_6502_INFO(_T("LDX #$data"),     _T("A2"), _T("立即寻址"),           _T("2"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → X")),
    ASM_6502_INFO(_T("LDX $addr"),      _T("A6"), _T("零页寻址"),           _T("3"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → X")),
    ASM_6502_INFO(_T("LDX $addr16"),    _T("AE"), _T("绝对寻址"),           _T("4"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → X")),
    ASM_6502_INFO(_T("LDX $addr,Y"),    _T("B6"), _T("零页Y变址"),          _T("4"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → X")),
    ASM_6502_INFO(_T("LDX $addr16,Y"),  _T("BE"), _T("绝对Y变址"),          _T("4\r\n(跳转到另一页时 +1)"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → X")),
    ASM_6502_INFO(_T("LDY #$data"),     _T("A0"), _T("立即寻址"),           _T("2"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → Y")),
    ASM_6502_INFO(_T("LDY $addr"),      _T("A4"), _T("零页寻址"),           _T("3"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → Y")),
    ASM_6502_INFO(_T("LDY $addr16"),    _T("AC"), _T("绝对寻址"),           _T("4"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → Y")),
    ASM_6502_INFO(_T("LDY $addr,X"),    _T("B4"), _T("零页X变址"),          _T("4"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → Y")),
    ASM_6502_INFO(_T("LDY $addr16,X"),  _T("BC"), _T("绝对X变址"),          _T("4\r\n(跳转到另一页时 +1)"), _T("NvbdiZc"), _T("由存储器取数送入累加器\r\nM → Y")),
    ASM_6502_INFO(_T("LSR"),            _T("4A"), _T("累加器寻址"),         _T("2"), _T("NvbdiZC (N=0)"), _T("逻辑右移指令，将字节内各位依次向右移1位，\r\n最低位移进标志位C，最高位补0。对于无符号数和正数相当于乘1/2")),
    ASM_6502_INFO(_T("LSR $data"),      _T("46"), _T("零页寻址"),           _T("5"), _T("NvbdiZC (N=0)"), _T("逻辑右移指令，将字节内各位依次向右移1位，\r\n最低位移进标志位C，最高位补0。对于无符号数和正数相当于乘1/2")),
    ASM_6502_INFO(_T("LSR $addr16"),    _T("4E"), _T("绝对寻址"),           _T("6"), _T("NvbdiZC (N=0)"), _T("逻辑右移指令，将字节内各位依次向右移1位，\r\n最低位移进标志位C，最高位补0。对于无符号数和正数相当于乘1/2")),
    ASM_6502_INFO(_T("LSR $addr,X"),    _T("56"), _T("零页X变址"),          _T("6"), _T("NvbdiZC (N=0)"), _T("逻辑右移指令，将字节内各位依次向右移1位，\r\n最低位移进标志位C，最高位补0。对于无符号数和正数相当于乘1/2")),
    ASM_6502_INFO(_T("LSR $addr16,X"),  _T("5E"), _T("绝对X变址"),          _T("7"), _T("NvbdiZC (N=0)"), _T("逻辑右移指令，将字节内各位依次向右移1位，\r\n最低位移进标志位C，最高位补0。对于无符号数和正数相当于乘1/2")),
    ASM_6502_INFO(_T("NOP"),            _T("EA"), _T("隐含寻址"),           _T("2"), _T("无影响"), _T("不做任何工作")),
    ASM_6502_INFO(_T("ORA ($addr,X)"),  _T("01"), _T("先变址X后间址"),      _T("6"), _T("NvbdiZc"), _T("寄存器与累加器相或，结果送累加器\r\nA ∨ M → A")),
    ASM_6502_INFO(_T("ORA $addr"),      _T("05"), _T("零页寻址"),           _T("3"), _T("NvbdiZc"), _T("寄存器与累加器相或，结果送累加器\r\nA ∨ M → A")),
    ASM_6502_INFO(_T("ORA #$data"),     _T("09"), _T("立即寻址"),           _T("2"), _T("NvbdiZc"), _T("寄存器与累加器相或，结果送累加器\r\nA ∨ M → A")),
    ASM_6502_INFO(_T("ORA $addr16"),    _T("0D"), _T("绝对寻址"),           _T("4"), _T("NvbdiZc"), _T("寄存器与累加器相或，结果送累加器\r\nA ∨ M → A")),
    ASM_6502_INFO(_T("ORA ($addr),Y"),  _T("11"), _T("后变址Y间址"),        _T("5\r\n(跳转到另一页时 +1)"), _T("NvbdiZc"), _T("寄存器与累加器相或，结果送累加器\r\nA ∨ M → A")),
    ASM_6502_INFO(_T("ORA $addr,X"),    _T("15"), _T("零页X变址"),          _T("4"), _T("NvbdiZc"), _T("寄存器与累加器相或，结果送累加器\r\nA ∨ M → A")),
    ASM_6502_INFO(_T("ORA $addr16,Y"),  _T("19"), _T("绝对Y变址"),          _T("4\r\n(跳转到另一页时 +1)"), _T("NvbdiZc"), _T("寄存器与累加器相或，结果送累加器\r\nA ∨ M → A")),
    ASM_6502_INFO(_T("ORA $addr16,X"),  _T("1D"), _T("绝对X变址"),          _T("4\r\n(跳转到另一页时 +1)"), _T("NvbdiZc"), _T("寄存器与累加器相或，结果送累加器\r\nA ∨ M → A")),
    ASM_6502_INFO(_T("PHA"),            _T("48"), _T("隐含寻址"),           _T("3"), _T("无影响"), _T("累加器进栈指令")),
    ASM_6502_INFO(_T("PHP"),            _T("08"), _T("隐含寻址"),           _T("3"), _T("无影响"), _T("标志寄存器P进栈指令")),
    ASM_6502_INFO(_T("PLA"),            _T("68"), _T("隐含寻址"),           _T("4"), _T("NvbdiZc"), _T("累加器出栈指令")),
    ASM_6502_INFO(_T("PLP"),            _T("28"), _T("隐含寻址"),           _T("4"), _T("NVBDIZC"), _T("标志寄存器P出栈指令")),
    ASM_6502_INFO(_T("ROL"),            _T("2A"), _T("累加器寻址"),         _T("2"), _T("NvbdiZC"), _T("循环左移指令，将字节内容连同进位C一起依次向左移1位")),
    ASM_6502_INFO(_T("ROL $data"),      _T("26"), _T("零页寻址"),           _T("5"), _T("NvbdiZC"), _T("循环左移指令，将字节内容连同进位C一起依次向左移1位")),
    ASM_6502_INFO(_T("ROL $addr16"),    _T("2E"), _T("绝对寻址"),           _T("6"), _T("NvbdiZC"), _T("循环左移指令，将字节内容连同进位C一起依次向左移1位")),
    ASM_6502_INFO(_T("ROL $addr,X"),    _T("36"), _T("零页X变址"),          _T("6"), _T("NvbdiZC"), _T("循环左移指令，将字节内容连同进位C一起依次向左移1位")),
    ASM_6502_INFO(_T("ROL $addr16,X"),  _T("3E"), _T("绝对X变址"),          _T("7"), _T("NvbdiZC"), _T("循环左移指令，将字节内容连同进位C一起依次向左移1位")),
    ASM_6502_INFO(_T("ROR"),            _T("6A"), _T("累加器寻址"),         _T("2"), _T("NvbdiZC"), _T("循环右移指令，将字节内容连同进位C一起依次向右移1位")),
    ASM_6502_INFO(_T("ROR $data"),      _T("66"), _T("零页寻址"),           _T("5"), _T("NvbdiZC"), _T("循环右移指令，将字节内容连同进位C一起依次向右移1位")),
    ASM_6502_INFO(_T("ROR $addr16"),    _T("6E"), _T("绝对寻址"),           _T("6"), _T("NvbdiZC"), _T("循环右移指令，将字节内容连同进位C一起依次向右移1位")),
    ASM_6502_INFO(_T("ROR $addr,X"),    _T("76"), _T("零页X变址"),          _T("6"), _T("NvbdiZC"), _T("循环右移指令，将字节内容连同进位C一起依次向右移1位")),
    ASM_6502_INFO(_T("ROR $addr16,X"),  _T("7E"), _T("绝对X变址"),          _T("7"), _T("NvbdiZC"), _T("循环右移指令，将字节内容连同进位C一起依次向右移1位")),
    ASM_6502_INFO(_T("RTI"),            _T("40"), _T("隐含寻址"),           _T("6"), _T("NVBDIZC"), _T("中断返回")),
    ASM_6502_INFO(_T("RTS"),            _T("60"), _T("隐含寻址"),           _T("6"), _T("无影响"), _T("从主程序返回指令")),
    ASM_6502_INFO(_T("SBC ($addr,X)"),  _T("E1"), _T("先变址X后间址"),      _T("6"), _T("NVbdiZC"), _T("从累加器减去存储器和进位标志C，结果送累加器\r\nA - M - C → A")),
    ASM_6502_INFO(_T("SBC $addr"),      _T("E5"), _T("零页寻址"),           _T("3"), _T("NVbdiZC"), _T("从累加器减去存储器和进位标志C，结果送累加器\r\nA - M - C → A")),
    ASM_6502_INFO(_T("SBC #$data"),     _T("E9"), _T("立即寻址"),           _T("2"), _T("NVbdiZC"), _T("从累加器减去存储器和进位标志C，结果送累加器\r\nA - M - C → A")),
    ASM_6502_INFO(_T("SBC $addr16"),    _T("ED"), _T("绝对寻址"),           _T("4"), _T("NVbdiZC"), _T("从累加器减去存储器和进位标志C，结果送累加器\r\nA - M - C → A")),
    ASM_6502_INFO(_T("SBC ($addr),Y"),  _T("F1"), _T("后变址Y间址"),        _T("5\r\n(跳转到另一页时 +1)"), _T("NVbdiZC"), _T("从累加器减去存储器和进位标志C，结果送累加器\r\nA - M - C → A")),
    ASM_6502_INFO(_T("SBC $addr,X"),    _T("F5"), _T("零页X变址"),          _T("4"), _T("NVbdiZC"), _T("从累加器减去存储器和进位标志C，结果送累加器\r\nA - M - C → A")),
    ASM_6502_INFO(_T("SBC $addr16,Y"),  _T("F9"), _T("绝对Y变址"),          _T("4\r\n(跳转到另一页时 +1)"), _T("NVbdiZC"), _T("从累加器减去存储器和进位标志C，结果送累加器\r\nA - M - C → A")),
    ASM_6502_INFO(_T("SBC $addr16,X"),  _T("FD"), _T("绝对X变址"),          _T("4\r\n(跳转到另一页时 +1)"), _T("NVbdiZC"), _T("从累加器减去存储器和进位标志C，结果送累加器\r\nA - M - C → A")),
    ASM_6502_INFO(_T("SEC"),            _T("38"), _T("隐含寻址"),           _T("2"), _T("nvbdizC (C=1)"), _T("置进位标志C\r\n1 → C")),
    ASM_6502_INFO(_T("SED"),            _T("F8"), _T("隐含寻址"),           _T("2"), _T("nvbDizc (D=1)"), _T("置十进制运算标志D\r\n1 → D")),
    ASM_6502_INFO(_T("SEI"),            _T("78"), _T("隐含寻址"),           _T("2"), _T("nvbdIzc (I=1)"), _T("置位中断禁止标志I\r\n1 → I")),
    ASM_6502_INFO(_T("STA ($addr,X)"),  _T("81"), _T("先变址X后间址"),      _T("6"), _T("无影响"), _T("将累加器的内容送入存储器\r\nA → M")),
    ASM_6502_INFO(_T("STA $addr"),      _T("85"), _T("零页寻址"),           _T("3"), _T("无影响"), _T("将累加器的内容送入存储器\r\nA → M")),
    ASM_6502_INFO(_T("STA $addr16"),    _T("8D"), _T("绝对寻址"),           _T("4"), _T("无影响"), _T("将累加器的内容送入存储器\r\nA → M")),
    ASM_6502_INFO(_T("STA ($addr),Y"),  _T("91"), _T("后变址Y间址"),        _T("6"), _T("无影响"), _T("将累加器的内容送入存储器\r\nA → M")),
    ASM_6502_INFO(_T("STA $addr,X"),    _T("95"), _T("零页X变址"),          _T("4"), _T("无影响"), _T("将累加器的内容送入存储器\r\nA → M")),
    ASM_6502_INFO(_T("STA $addr16,Y"),  _T("99"), _T("绝对Y变址"),          _T("5"), _T("无影响"), _T("将累加器的内容送入存储器\r\nA → M")),
    ASM_6502_INFO(_T("STA $addr16,X"),  _T("9D"), _T("绝对X变址"),          _T("5"), _T("无影响"), _T("将累加器的内容送入存储器\r\nA → M")),
    ASM_6502_INFO(_T("STX $addr"),      _T("86"), _T("零页寻址"),           _T("3"), _T("无影响"), _T("将寄存器X的内容送入存储器\r\nX → M")),
    ASM_6502_INFO(_T("STX $addr16"),    _T("8E"), _T("绝对寻址"),           _T("4"), _T("无影响"), _T("将寄存器X的内容送入存储器\r\nX → M")),
    ASM_6502_INFO(_T("STX $addr,Y"),    _T("96"), _T("零页Y变址"),          _T("4"), _T("无影响"), _T("将寄存器X的内容送入存储器\r\nX → M")),
    ASM_6502_INFO(_T("STY $addr"),      _T("84"), _T("零页寻址"),           _T("3"), _T("无影响"), _T("将寄存器Y的内容送入存储器\r\nY → M")),
    ASM_6502_INFO(_T("STY $addr16"),    _T("8C"), _T("绝对寻址"),           _T("4"), _T("无影响"), _T("将寄存器Y的内容送入存储器\r\nY → M")),
    ASM_6502_INFO(_T("STY $addr,X"),    _T("94"), _T("零页X变址"),          _T("4"), _T("无影响"), _T("将寄存器Y的内容送入存储器\r\nY → M")),
    ASM_6502_INFO(_T("TAX"),            _T("AA"), _T("寄存器寻址"),         _T("2"), _T("NvbdiZc"), _T("将累加器A的内容送入变址寄存器X")),
    ASM_6502_INFO(_T("TAY"),            _T("A8"), _T("寄存器寻址"),         _T("2"), _T("NvbdiZC"), _T("将累加器A的内容送入变址寄存器Y")),
    ASM_6502_INFO(_T("TSX"),            _T("BA"), _T("寄存器寻址"),         _T("2"), _T("NvbdiZC"), _T("将堆栈指针S的内容送入变址寄存器X")),
    ASM_6502_INFO(_T("TXA"),            _T("8A"), _T("寄存器寻址"),         _T("2"), _T("NvbdiZC"), _T("将变址寄存器X的内容送入累加器A")),
    ASM_6502_INFO(_T("TXS"),            _T("9A"), _T("寄存器寻址"),         _T("2"), _T("无影响"), _T("将变址寄存器X的内容送入堆栈指针S")),
    ASM_6502_INFO(_T("TYA"),            _T("98"), _T("寄存器寻址"),         _T("2"), _T("NvbdiZC"), _T("将变址寄存器Y的内容送入累加器A"))
};

std::vector<CString> g_6502_asm;
std::map<CString, int>g_6502_op;

HWND g_hWnd = NULL;
HHOOK g_hKeyHook = NULL;

CString g_strFalg;
CString g_strAddr;
CString g_strAsm;
CString g_strMachine;

UINT g_uData8 = 0x13;
UINT g_uAddr8 = 0xAA;
WORD g_uAddr16 = 0xFF20;
WORD g_uOffset8 = 0x32;
CString g_strWarn;

void MoveWindowToCenter(HWND hwnd, HWND hParent);

void InitData(HWND hWnd)
{
    HWND hAsm = GetDlgItem(hWnd, IDC_COMBO_ASM);
    HWND hOp = GetDlgItem(hWnd, IDC_COMBO_OP);
    HWND hAddr = GetDlgItem(hWnd, IDC_COMBO_ADDR);

    RECT rt;
    POINT p1;

    GetWindowRect(hAsm, &rt);
    rt.bottom = rt.top + 256;
    p1.x = rt.left;
    p1.y = rt.top;
    ScreenToClient(hWnd, &p1);
    MoveWindow(hAsm, p1.x, p1.y, rt.right - rt.left, rt.bottom - rt.top, FALSE);

    GetWindowRect(hOp, &rt);
    rt.bottom = rt.top + 256;
    p1.x = rt.left;
    p1.y = rt.top;
    ScreenToClient(hWnd, &p1);
    MoveWindow(hOp, p1.x, p1.y, rt.right - rt.left, rt.bottom - rt.top, FALSE);

    GetWindowRect(hAddr, &rt);
    rt.bottom = rt.top + 256;
    p1.x = rt.left;
    p1.y = rt.top;
    ScreenToClient(hWnd, &p1);
    MoveWindow(hAddr, p1.x, p1.y, rt.right - rt.left, rt.bottom - rt.top, FALSE);

    CString strAsm;
    int nIndex = 0;
    for (auto item : g_6502_set)
    {
        if (0 != _tcsnicmp(item.mAsm, strAsm, 3))
        {
            g_6502_asm.push_back(item.mAsm.Left(3).GetString());
        }
        strAsm = item.mAsm.GetString();
        nIndex++;
    }

    nIndex = 0;
    for (auto item : g_6502_set)
    {
        g_6502_op.insert(std::make_pair(item.mOp, nIndex));
        nIndex++;
    }

    for (auto item : g_6502_op)
    {
        SendMessage(hOp, CB_ADDSTRING, nIndex, (LPARAM)item.first.GetString());
    }

    nIndex = 0;
    for (auto item : g_6502_asm)
    {
        SendMessage(hAsm, CB_ADDSTRING, nIndex, (LPARAM)g_6502_asm[nIndex].GetString());
        nIndex++;
    }
}

CString GetWindowText(HWND hWnd)
{
    TCHAR szBuf[MAX_PATH];
    CString str;

    GetWindowText(hWnd, szBuf, _countof(szBuf));
    str = szBuf;

    return str;
}

CString GetDlgItemText(HWND hWnd, UINT uID)
{
    TCHAR szBuf[MAX_PATH];
    CString str;

    GetDlgItemText(hWnd, uID, szBuf, _countof(szBuf));
    str = szBuf;

    return str;
}

void UpdateData(HWND hWnd, HWND hCtrl)
{
    HWND hAsm = GetDlgItem(hWnd, IDC_COMBO_ASM);
    HWND hAddr = GetDlgItem(hWnd, IDC_COMBO_ADDR);
    HWND hOp = GetDlgItem(hWnd, IDC_COMBO_OP);
    HWND hFormat = GetDlgItem(hWnd, IDC_EDIT_FORMAT);
    HWND hCycle = GetDlgItem(hWnd, IDC_EDIT_CYCLE);
    HWND hDesc = GetDlgItem(hWnd, IDC_EDIT_DESC);

    //从助记符更新
    if (hCtrl == hAsm)
    {
        TCHAR szAmsBuf[MAX_PATH] = { 0 };
        int nIndex = 0;

        //获取助记符
        LRESULT nCursel = SendMessage(hAsm, CB_GETCURSEL, 0, 0);
        bool isSet = false;
        if (-1 == nCursel)
        {
            return;
        }

        SendMessage(hAsm, CB_GETLBTEXT, nCursel, (LPARAM)szAmsBuf);

        //操作码
        SendMessage(hAddr, CB_RESETCONTENT, 0, 0);
        nIndex = 0;
        for (auto& item : g_6502_set)
        {
            if (0 == _tcsnicmp(item.mAsm, szAmsBuf, 3))
            {
                //寻址添加
                SendMessage(hAddr, CB_ADDSTRING, nIndex, (LPARAM)item.mAddr.GetString());
                if (!isSet)
                {
                    auto info = g_6502_op.find(item.mOp);

                    int nIndex = 0;
                    int nDataIndex = 0;
                    for (auto &op : g_6502_op)
                    {
                        if (item.mOp == op.first)
                        {
                            SendMessage(hOp, CB_SETCURSEL, nIndex, 0);
                            nDataIndex = op.second;
                            break;
                        }

                        nIndex++;
                    }

                    SendMessage(hAddr, CB_SETCURSEL, 0, 0);
                    SetWindowText(hFormat, g_6502_set[nDataIndex].mAsm);
                    SetWindowText(hCycle, g_6502_set[nDataIndex].mCycle);
                    SetWindowText(hDesc, g_6502_set[nDataIndex].mDesc);
                    g_strFalg = g_6502_set[nDataIndex].mFlag;
                    g_strAddr = g_6502_set[nDataIndex].mAddr;
                    g_strAsm = g_6502_set[nDataIndex].mAsm.Left(3);
                    g_strMachine = g_6502_set[nDataIndex].mOp;
                    isSet = true;
                }
            }
            nIndex++;
        }
    }

    //从寻址更新
    if (hCtrl == hAddr)
    {
        TCHAR szAmsBuf[MAX_PATH] = { 0 };
        TCHAR szAddrBuf[MAX_PATH] = { 0 };
        LRESULT nCursel = 0;

        //获取寻址
        nCursel = SendMessage(hAddr, CB_GETCURSEL, 0, 0);
        if (-1 == nCursel)
        {
            return;
        }
        SendMessage(hAddr, CB_GETLBTEXT, nCursel, (LPARAM)szAddrBuf);

        //获取助记符
        nCursel = SendMessage(hAsm, CB_GETCURSEL, 0, 0);
        if (-1 == nCursel)
        {
            return;
        }
        SendMessage(hAsm, CB_GETLBTEXT, nCursel, (LPARAM)szAmsBuf);

        //查找操作码
        int nIndex = 0;
        for (auto& item : g_6502_set)
        {
            if (0 == _tcsnicmp(item.mAsm, szAmsBuf, 3) && item.mAddr == szAddrBuf)
            {
                int nIndex = 0;
                int nDataIndex = 0;
                for (auto& op : g_6502_op)
                {
                    if (item.mOp == op.first)
                    {
                        SendMessage(hOp, CB_SETCURSEL, nIndex, 0);
                        nDataIndex = op.second;
                        break;
                    }

                    nIndex++;
                }

                SendMessage(hOp, CB_SETCURSEL, nIndex, 0);
                SetWindowText(hFormat, g_6502_set[nDataIndex].mAsm);
                SetWindowText(hCycle, g_6502_set[nDataIndex].mCycle);
                SetWindowText(hDesc, g_6502_set[nDataIndex].mDesc);
                g_strFalg = g_6502_set[nDataIndex].mFlag;
                g_strAddr = g_6502_set[nDataIndex].mAddr;
                g_strAsm = g_6502_set[nDataIndex].mAsm.Left(3);
                g_strMachine = g_6502_set[nDataIndex].mOp;

                break;
            }
            nIndex++;
        }
    }

    //从机器码更新
    if (hCtrl == hOp)
    {
        TCHAR szOpBuf[MAX_PATH] = { 0 };
        int nIndex = 0;
        LRESULT nCursel = SendMessage(hOp, CB_GETCURSEL, 0, 0);
        if (-1 == nCursel)
        {
            return;
        }

        SendMessage(hOp, CB_GETLBTEXT, nCursel, (LPARAM)szOpBuf);

        nIndex = 0;
        int nDataIndex = 0;
        for (auto& item : g_6502_op)
        {
            if (item.first == szOpBuf)
            {
                nDataIndex = item.second;
                break;
            }
            nIndex++;
        }

        SetWindowText(hFormat, g_6502_set[nDataIndex].mAsm);
        SetWindowText(hCycle, g_6502_set[nDataIndex].mCycle);
        SetWindowText(hDesc, g_6502_set[nDataIndex].mDesc);
        SetWindowText(hAddr, g_6502_set[nDataIndex].mAddr);
        g_strFalg = g_6502_set[nDataIndex].mFlag;
        g_strAddr = g_6502_set[nDataIndex].mAddr;
        g_strAsm = g_6502_set[nDataIndex].mAsm.Left(3);
        g_strMachine = g_6502_set[nDataIndex].mOp;

        //助记符
        CString strAsm = g_6502_set[nDataIndex].mAsm;
        nIndex = 0;
        for (auto item : g_6502_asm)
        {
            if (0 == _tcsnicmp(item, strAsm, 3))
            {
                SendMessage(hAsm, CB_SETCURSEL, nIndex, 0);
                break;
            }
            nIndex++;
        }

        //寻址
        SendMessage(hAddr, CB_RESETCONTENT, 0, 0);
        nIndex = 0;
        for (auto& item : g_6502_set)
        {
            if (0 == _tcsnicmp(item.mAsm, strAsm, 3))
            {
                SendMessage(hAddr, CB_ADDSTRING, nIndex, (LPARAM)item.mAddr.GetString());
                if (item.mAddr == g_6502_set[nDataIndex].mAddr)
                {
                    SendMessage(hAddr, CB_SETCURSEL, nIndex, 0);
                }

                nIndex++;
            }
        }
    }

    //标志
    {
        UINT uCheck = BST_UNCHECKED;
        uCheck = g_strFalg.Find(_T('N')) >= 0 ? BST_CHECKED : BST_UNCHECKED;
        CheckDlgButton(hWnd, IDC_CHECK_N, uCheck);
        uCheck = g_strFalg.Find(_T('V')) >= 0 ? BST_CHECKED : BST_UNCHECKED;
        CheckDlgButton(hWnd, IDC_CHECK_V, uCheck);
        uCheck = g_strFalg.Find(_T('B')) >= 0 ? BST_CHECKED : BST_UNCHECKED;
        CheckDlgButton(hWnd, IDC_CHECK_B, uCheck);
        uCheck = g_strFalg.Find(_T('D')) >= 0 ? BST_CHECKED : BST_UNCHECKED;
        CheckDlgButton(hWnd, IDC_CHECK_D, uCheck);
        uCheck = g_strFalg.Find(_T('I')) >= 0 ? BST_CHECKED : BST_UNCHECKED;
        CheckDlgButton(hWnd, IDC_CHECK_I, uCheck);
        uCheck = g_strFalg.Find(_T('Z')) >= 0 ? BST_CHECKED : BST_UNCHECKED;
        CheckDlgButton(hWnd, IDC_CHECK_Z, uCheck);
        uCheck = g_strFalg.Find(_T('C')) >= 0 ? BST_CHECKED : BST_UNCHECKED;
        CheckDlgButton(hWnd, IDC_CHECK_C, uCheck);
    }

    RefreshCode(hWnd);
    g_strWarn = _T("操作完成");
    SetDlgItemText(g_hWnd, IDC_STATIC_WARN, g_strWarn);
}

void RefreshCode(HWND hWnd)
{
    CString strData8;
    CString strAddr8;
    CString strAddr16;
    CString strOffset8;

    strData8 = GetDlgItemText(hWnd, IDC_EDIT_DATA8);
    strAddr8 = GetDlgItemText(hWnd, IDC_EDIT_ADDR8);
    strAddr16 = GetDlgItemText(hWnd, IDC_EDIT_ADDR16);
    strOffset8 = GetDlgItemText(hWnd, IDC_EDIT_OFFSET8);

    UINT uData8 = _tcstoul(strData8, NULL, 16);
    UINT uAddr8 = _tcstoul(strAddr8, NULL, 16);
    WORD uAddr16 = _tcstoul(strAddr16, NULL, 16);
    WORD uOffset8 = _tcstoul(strOffset8, NULL, 16);

    HWND hEditAsm = GetDlgItem(hWnd, IDC_EDIT_FORMAT_ASM);
    HWND hEditMachine = GetDlgItem(hWnd, IDC_EDIT_FORMAT_MACHINE);

    {
        CString strFormatAsm;
        CString strFormatMachine;

        CheckDlgButton(hWnd, IDC_CHECK_DATA8, BST_UNCHECKED);
        CheckDlgButton(hWnd, IDC_CHECK_ADDR8, BST_UNCHECKED);
        CheckDlgButton(hWnd, IDC_CHECK_ADDR16, BST_UNCHECKED);
        CheckDlgButton(hWnd, IDC_CHECK_OFFSET8, BST_UNCHECKED);

        if (g_strAddr == _T("立即寻址"))
        {
            CheckDlgButton(hWnd, IDC_CHECK_DATA8, BST_CHECKED);
            strFormatAsm.Format(_T("%s #$%0.2X"), g_strAsm.GetString(), uData8);
            strFormatMachine.Format(_T("%s %0.2X"), g_strMachine.GetString(), uData8);
        }
        else if (g_strAddr == _T("相对寻址"))
        {
            CheckDlgButton(hWnd, IDC_CHECK_OFFSET8, BST_CHECKED);
            strFormatAsm.Format(_T("%s Label"), g_strAsm.GetString());
            strFormatMachine.Format(_T("%s %0.2X"), g_strMachine.GetString(), uOffset8);
        }
        else if (g_strAddr == _T("零页寻址"))
        {
            CheckDlgButton(hWnd, IDC_CHECK_ADDR8, BST_CHECKED);
            strFormatAsm.Format(_T("%s $%0.2X"), g_strAsm.GetString(), uAddr8);
            strFormatMachine.Format(_T("%s %0.2X"), g_strMachine.GetString(), uAddr8);
        }
        else if (g_strAddr == _T("零页X变址"))
        {
            CheckDlgButton(hWnd, IDC_CHECK_ADDR8, BST_CHECKED);
            strFormatAsm.Format(_T("%s $%0.2X,X"), g_strAsm.GetString(), uAddr8);
            strFormatMachine.Format(_T("%s %0.2X,X"), g_strMachine.GetString(), uAddr8);
        }
        else if (g_strAddr == _T("零页Y变址"))
        {
            CheckDlgButton(hWnd, IDC_CHECK_ADDR8, BST_CHECKED);
            strFormatAsm.Format(_T("%s $%0.2X,Y"), g_strAsm.GetString(), uAddr8);
            strFormatMachine.Format(_T("%s %0.2X,Y"), g_strMachine.GetString(), uAddr8);
        }
        else if (g_strAddr == _T("绝对寻址"))
        {
            CheckDlgButton(hWnd, IDC_CHECK_ADDR16, BST_CHECKED);
            strFormatAsm.Format(_T("%s $%0.4X"), g_strAsm.GetString(), uAddr16);
            strFormatMachine.Format(_T("%s %0.2X %0.2X"), g_strMachine.GetString(), uAddr16 & 0xFF, uAddr16 >> 8);
        }
        else if (g_strAddr == _T("绝对X变址"))
        {
            CheckDlgButton(hWnd, IDC_CHECK_ADDR16, BST_CHECKED);
            strFormatAsm.Format(_T("%s $%0.4X,X"), g_strAsm.GetString(), uAddr16);
            strFormatMachine.Format(_T("%s %0.2X %0.2X"), g_strMachine.GetString(), uAddr16 & 0xFF, uAddr16 >> 8);
        }
        else if (g_strAddr == _T("绝对Y变址"))
        {
            CheckDlgButton(hWnd, IDC_CHECK_ADDR16, BST_CHECKED);
            strFormatAsm.Format(_T("%s $%0.4X,Y"), g_strAsm.GetString(), uAddr16);
            strFormatMachine.Format(_T("%s %0.2X %0.2X"), g_strMachine.GetString(), uAddr16 & 0xFF, uAddr16 >> 8);
        }
        else if (g_strAddr == _T("先变址X后间址"))
        {
            CheckDlgButton(hWnd, IDC_CHECK_ADDR8, BST_CHECKED);
            strFormatAsm.Format(_T("%s ($%0.2X)"), g_strAsm.GetString(), uAddr8);
            strFormatMachine.Format(_T("%s %0.2X"), g_strMachine.GetString(), uAddr8);
        }
        else if (g_strAddr == _T("后变址Y间址"))
        {
            CheckDlgButton(hWnd, IDC_CHECK_ADDR8, BST_CHECKED);
            strFormatAsm.Format(_T("%s ($%0.2X),Y"), g_strAsm.GetString(), uAddr8);
            strFormatMachine.Format(_T("%s %0.2X"), g_strMachine.GetString(), uAddr8);
        }
        else if (g_strAddr == _T("间接寻址"))
        {
            CheckDlgButton(hWnd, IDC_CHECK_ADDR16, BST_CHECKED);
            strFormatAsm.Format(_T("%s ($%0.4X)"), g_strAsm.GetString(), uAddr16);
            strFormatMachine.Format(_T("%s %0.2X %0.2X"), g_strMachine.GetString(), uAddr16 & 0xFF, uAddr16 >> 8);
        }
        else if (g_strAddr == _T("累加器寻址"))
        {
            strFormatAsm.Format(_T("%s"), g_strAsm.GetString());
            strFormatMachine.Format(_T("%s"), g_strMachine.GetString());
        }
        else if (g_strAddr == _T("隐含寻址"))
        {
            strFormatAsm.Format(_T("%s"), g_strAsm.GetString());
            strFormatMachine.Format(_T("%s"), g_strMachine.GetString());
        }
        else if (g_strAddr == _T("寄存器寻址"))
        {
            strFormatAsm.Format(_T("%s"), g_strAsm.GetString());
            strFormatMachine.Format(_T("%s"), g_strMachine.GetString());
        }

        SetWindowText(hEditAsm, strFormatAsm);
        SetWindowText(hEditMachine, strFormatMachine);
    }
}

void FindData()
{
    HWND hAsm = GetDlgItem(g_hWnd, IDC_COMBO_ASM);
    HWND hAddr = GetDlgItem(g_hWnd, IDC_COMBO_ADDR);
    HWND hOp = GetDlgItem(g_hWnd, IDC_COMBO_OP);
    HWND hFormat = GetDlgItem(g_hWnd, IDC_EDIT_FORMAT);
    HWND hCycle = GetDlgItem(g_hWnd, IDC_EDIT_CYCLE);
    HWND hDesc = GetDlgItem(g_hWnd, IDC_EDIT_DESC);
    HWND hFlag = GetDlgItem(g_hWnd, IDC_EDIT_FLAG);
    HWND hEditAsm = GetDlgItem(g_hWnd, IDC_EDIT_FORMAT_ASM);
    HWND hEditMachine = GetDlgItem(g_hWnd, IDC_EDIT_FORMAT_MACHINE);

    TCHAR szBuf[MAX_PATH] = { 0 };
    int nIndex = 0;

    GetDlgItemText(g_hWnd, IDC_EDIT_FIND, szBuf, _countof(szBuf));

    //查找机器码
    nIndex = 0;
    for (auto& item : g_6502_op)
    {
        if (0 == item.first.CompareNoCase(szBuf))
        {
            SendMessage(hOp, CB_SETCURSEL, nIndex, 0);
            UpdateData(g_hWnd, hOp);
            return;
        }
        nIndex++;
    }

    //查找助记符
    nIndex = 0;
    for (auto item : g_6502_asm)
    {
        if (0 == item.CompareNoCase(szBuf))
        {
            SendMessage(hAsm, CB_SETCURSEL, nIndex, 0);
            UpdateData(g_hWnd, hAsm);
            return;
        }
        nIndex++;
    }

    //未找到
    SendMessage(hAsm, CB_SETCURSEL, (WPARAM)- 1, 0);
    SendMessage(hAddr, CB_RESETCONTENT, 0, 0);
    SendMessage(hOp, CB_SETCURSEL, (WPARAM)-1, 0);
    SetWindowText(hFormat, _T(""));
    SetWindowText(hCycle, _T(""));
    SetWindowText(hDesc, _T(""));
    SetWindowText(hFlag, _T(""));
    SetWindowText(hAddr, _T(""));
    SetWindowText(hEditAsm, _T(""));
    SetWindowText(hEditMachine, _T(""));
    SetDlgItemText(g_hWnd, IDC_STATIC_WARN, _T("未查找到相关数据"));

}

INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_INITDIALOG:
    {
        g_hWnd = hWnd;

        ImmDisableIME(GetCurrentThreadId());

        HICON hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON));
        SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
        SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);

        UpdateHexText();
        UpdateDecText();
        UpdateBinText();

        InitData(hWnd);
        SetDlgItemText(g_hWnd, IDC_STATIC_WARN, _T("未选中数据"));

        g_hKeyHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, GetModuleHandle(0), GetCurrentThreadId());
    }
    break;
    case WM_CLOSE:
    {
        EndDialog(hWnd, WM_CLOSE);
    }
    break;
    case WM_COMMAND:
    {
        DWORD notifyID = HIWORD(wParam);
        //DWORD cmdID = LOWORD(wParam);
        HWND hCtrl = (HWND)lParam;

        if (CBN_SELCHANGE == notifyID)
        {
            UpdateData(hWnd, hCtrl);
            break;
        }

        switch (LOWORD(wParam))
        {
        case IDM_FILE_EXIT:
        {
            PostMessage(hWnd, WM_CLOSE, 0, 0);
        }
        break;
        case IDM_SETTING_TOPMOST:
        {
            HMENU hMenu = GetMenu(hWnd);
            DWORD dwState = GetMenuState(GetMenu(hWnd), IDM_SETTING_TOPMOST, MF_BYCOMMAND | MF_CHECKED);
            if (MF_CHECKED & dwState)
            {
                SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
                CheckMenuItem(hMenu, IDM_SETTING_TOPMOST, MF_BYCOMMAND | MF_UNCHECKED);
            }
            else
            {
                SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
                CheckMenuItem(hMenu, IDM_SETTING_TOPMOST, MF_BYCOMMAND | MF_CHECKED);
            }
        }
        break;
        case IDC_BUTTON_REFRESH_CODE:
        {
            RefreshCode(hWnd);
        }
        break;
        case IDM_HELP_ABOUT:
        {
            DialogBox(NULL, MAKEINTRESOURCE(IDD_DIALOG_ABOUT), hWnd, AboutProc);
        }
        break;
        default:
            break;
        }
    }
    break;
    default:
        return FALSE;
    }

    return TRUE;
}

INT_PTR CALLBACK AboutProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_INITDIALOG:
    {
        MoveWindowToCenter(hWnd, GetParent(hWnd));
    }
    break;
    case WM_CLOSE:
    {
        EndDialog(hWnd, WM_CLOSE);
    }
    break;
    case WM_COMMAND:
    {
        //DWORD notifyID = HIWORD(wParam);
        DWORD cmdID = LOWORD(wParam);
        //HWND hCtrl = (HWND)lParam;

        if (IDOK == cmdID)
        {
            EndDialog(hWnd, WM_CLOSE);
        }
    }
    break;// g_hLink is the handle of the SysLink control.
    case WM_NOTIFY:
    {
        switch (((LPNMHDR)lParam)->code)
        {
        case NM_CLICK:          // Fall through to the next case.
        case NM_RETURN:
        {
            PNMLINK pNMLink = (PNMLINK)lParam;
            LITEM   item = pNMLink->item;
            HWND hLinkWnd = GetDlgItem(hWnd, IDC_SYSLINK_ADDR);

            if ((((LPNMHDR)lParam)->hwndFrom == hLinkWnd) && (item.iLink == 0))
            {
                ShellExecute(NULL, L"open", item.szUrl, NULL, NULL, SW_SHOW);
            }

            else if (wcscmp(item.szID, L"idInfo") == 0)
            {
                MessageBox(hWnd, L"This isn't much help.", L"Example", MB_OK);
            }
            break;
        }
        }
    }
    break;
    default:
        return FALSE;
    }

    return TRUE;
}

INT_PTR CALLBACK WarnProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_INITDIALOG:
    {
        MoveWindowToCenter(hWnd, GetParent(hWnd));

        SetDlgItemText(hWnd, IDC_EDIT_WARN, g_strWarn);
    }
    break;
    case WM_CLOSE:
    {
        EndDialog(hWnd, WM_CLOSE);
    }
    break;
    case WM_COMMAND:
    {
        DWORD cmdID = LOWORD(wParam);
        if (IDOK == cmdID)
        {
            EndDialog(hWnd, WM_CLOSE);
        }
    }
    break;
    default:
        return FALSE;
    }

    return TRUE;
}

void MoveWindowToCenter(HWND hwnd, HWND hParent)
{
    RECT rectParent = { 0 };
    RECT rectChild = { 0 };
    LONG dwParentW = 0;
    LONG dwParentH = 0;
    LONG dwChildW = 0;
    LONG dwChildH = 0;

    if (NULL == hParent)
    {
        hParent = GetDesktopWindow();
    }

    GetWindowRect(hwnd, &rectChild);
    GetWindowRect(hParent, &rectParent);

    dwParentW = rectParent.right - rectParent.left;
    dwParentH = rectParent.bottom - rectParent.top;
    dwChildW = rectChild.right - rectChild.left;
    dwChildH = rectChild.bottom - rectChild.top;

    MoveWindow(hwnd, rectParent.left + (dwParentW - dwChildW) / 2,
        rectParent.top + (dwParentH - dwChildH) / 2, dwChildW, dwChildH, TRUE);
}

void UpdateHexData()
{
    CString strData8 = GetDlgItemText(g_hWnd, IDC_EDIT_DATA8);
    CString strAddr8 = GetDlgItemText(g_hWnd, IDC_EDIT_ADDR8);
    CString strAddr16 = GetDlgItemText(g_hWnd, IDC_EDIT_ADDR16);
    CString strOffset8 = GetDlgItemText(g_hWnd, IDC_EDIT_OFFSET8);

    g_uData8 = _tcstoull(strData8, NULL, 16);
    g_uAddr8 = _tcstoull(strAddr8, NULL, 16);
    g_uAddr16 = _tcstoull(strAddr16, NULL, 16);
    g_uOffset8 = _tcstoull(strOffset8, NULL, 16);
}

void UpdateDecData()
{
    CString strData8 = GetDlgItemText(g_hWnd, IDC_EDIT_DATA8_DEC);
    CString strAddr8 = GetDlgItemText(g_hWnd, IDC_EDIT_ADDR8_DEC);
    CString strAddr16 = GetDlgItemText(g_hWnd, IDC_EDIT_ADDR16_DEC);
    CString strOffset8 = GetDlgItemText(g_hWnd, IDC_EDIT_OFFSET8_DEC);

    g_uData8 = _tcstoull(strData8, NULL, 10);
    g_uAddr8 = _tcstoull(strAddr8, NULL, 10);
    g_uAddr16 = _tcstoull(strAddr16, NULL, 10);
    g_uOffset8 = _tcstoull(strOffset8, NULL, 10);
}

void UpdateBinData()
{
    CString strData8 = GetDlgItemText(g_hWnd, IDC_EDIT_DATA8_BIN);
    CString strAddr8 = GetDlgItemText(g_hWnd, IDC_EDIT_ADDR8_BIN);
    CString strAddr16 = GetDlgItemText(g_hWnd, IDC_EDIT_ADDR16_BIN);
    CString strOffset8 = GetDlgItemText(g_hWnd, IDC_EDIT_OFFSET8_BIN);

    g_uData8 = _tcstoull(strData8, NULL, 2);
    g_uAddr8 = _tcstoull(strAddr8, NULL, 2);
    g_uAddr16 = _tcstoull(strAddr16, NULL, 2);
    g_uOffset8 = _tcstoull(strOffset8, NULL, 2);
}

void UpdateHexText()
{
    CString strData8;
    CString strAddr8;
    CString strAddr16;
    CString strOffset8;

    strData8.Format(_T("%0.2x"), g_uData8);
    strAddr8.Format(_T("%0.2x"), g_uAddr8);
    strAddr16.Format(_T("%0.4x"), g_uAddr16);
    strOffset8.Format(_T("%0.2x"), g_uOffset8);

    SetDlgItemText(g_hWnd, IDC_EDIT_DATA8, strData8);
    SetDlgItemText(g_hWnd, IDC_EDIT_ADDR8, strAddr8);
    SetDlgItemText(g_hWnd, IDC_EDIT_ADDR16, strAddr16);
    SetDlgItemText(g_hWnd, IDC_EDIT_OFFSET8, strOffset8);
}

void UpdateDecText()
{
    CString strData8;
    CString strAddr8;
    CString strAddr16;
    CString strOffset8;

    strData8.Format(_T("%0.3u"), g_uData8);
    strAddr8.Format(_T("%0.3u"), g_uAddr8);
    strAddr16.Format(_T("%0.5u"), g_uAddr16);
    strOffset8.Format(_T("%0.3u"), g_uOffset8);

    SetDlgItemText(g_hWnd, IDC_EDIT_DATA8_DEC, strData8);
    SetDlgItemText(g_hWnd, IDC_EDIT_ADDR8_DEC, strAddr8);
    SetDlgItemText(g_hWnd, IDC_EDIT_ADDR16_DEC, strAddr16);
    SetDlgItemText(g_hWnd, IDC_EDIT_OFFSET8_DEC, strOffset8);
}

void UpdateBinText()
{
    TCHAR szData8[MAX_PATH] = { 0 };
    TCHAR szAddr8[MAX_PATH] = { 0 };
    TCHAR szAddr16[MAX_PATH] = { 0 };
    TCHAR szOffset8[MAX_PATH] = { 0 };

    _ultot_s(g_uData8, szData8, 2);
    _ultot_s(g_uAddr8, szAddr8, 2);
    _ultot_s(g_uAddr16, szAddr16, 2);
    _ultot_s(g_uOffset8, szOffset8, 2);

    CString strData8 = szData8;
    CString strAddr8 = szAddr8;
    CString strAddr16 = szAddr16;
    CString strOffset8 = szOffset8;

    CString strFormat;
    int nDataLen = 0;
    nDataLen = 8 - strData8.GetLength();
    if (nDataLen < 0)
    {
        nDataLen = 0;
    }

    strFormat.Format(_T("%%0.%dd%%s"), nDataLen);
    strData8.Format(strFormat, 0, strData8.GetString());

    nDataLen = 8 - strAddr8.GetLength();
    if (nDataLen < 0)
    {
        nDataLen = 0;
    }
    strFormat.Format(_T("%%0.%dd%%s"), nDataLen);
    strAddr8.Format(strFormat, 0, strAddr8.GetString());

    nDataLen = 16 - strAddr16.GetLength();
    if (nDataLen < 0)
    {
        nDataLen = 0;
    }
    strFormat.Format(_T("%%0.%dd%%s"), nDataLen);
    strAddr16.Format(strFormat, 0, strAddr16.GetString());

    nDataLen = 8 - strOffset8.GetLength();
    if (nDataLen < 0)
    {
        nDataLen = 0;
    }
    strFormat.Format(_T("%%0.%dd%%s"), nDataLen);
    strOffset8.Format(strFormat, 0, strOffset8.GetString());

    SetDlgItemText(g_hWnd, IDC_EDIT_DATA8_BIN, strData8);
    SetDlgItemText(g_hWnd, IDC_EDIT_ADDR8_BIN, strAddr8);
    SetDlgItemText(g_hWnd, IDC_EDIT_ADDR16_BIN, strAddr16);
    SetDlgItemText(g_hWnd, IDC_EDIT_OFFSET8_BIN, strOffset8);
}

BOOL CheckPreData(HWND hWndFocus, UINT vkCode, int nBeg, int nEnd, int nMax, int nRadix)
{
    CString strText = GetWindowText(hWndFocus);
    CString strLeft = strText.Left(nBeg);
    CString strRight = strText.Right(strText.GetLength() - nEnd);
    CString strMid;

    if (nBeg >= strText.GetLength())
    {
        return TRUE;
    }

    if (nEnd - nBeg > 0)
    {
        strMid += (TCHAR)vkCode;
        strRight = strText.Right(strText.GetLength() - (nBeg + 1));
        nBeg++;
        nEnd = nBeg;
    }
    else
    {
        strMid += (TCHAR)vkCode;
        strRight = strRight.Right(strRight.GetLength() - 1);
        nBeg++;
        nEnd++;
    }

    strText = strLeft;
    strText += strMid;
    strText += strRight;

    UINT ulValue = _tcstoull(strText, NULL, nRadix);

    if (ulValue <= nMax)
    {
        g_strWarn = _T("操作完成");
        SetDlgItemText(g_hWnd, IDC_STATIC_WARN, g_strWarn);

        SetWindowText(hWndFocus, strText);
        SendMessage(hWndFocus, EM_SETSEL, nBeg, nEnd);

        SendMessage(g_hWnd, WM_COMMAND, IDC_BUTTON_FIND, (LPARAM)hWndFocus);
        return FALSE;
    }

    if (10 == nRadix)
    {
        if (nMax <= 255)
        {
            g_strWarn.Format(_T("您的输入: %0.3d 超过最大数据输入范围: 255"), ulValue);
        }
        else
        {
            g_strWarn.Format(_T("您的输入: %0.5d 超过最大数据输入范围: 65535"), ulValue);
        }
    }

    SetDlgItemText(g_hWnd, IDC_STATIC_WARN, g_strWarn);

    return TRUE;
}

BOOL CheckDelData(HWND hWndFocus, UINT vkCode, int nBeg, int nEnd, int nRadix)
{
    CString strText = GetWindowText(hWndFocus);
    CString strLeft = strText.Left(nBeg);
    CString strRight = strText.Right(strText.GetLength() - nEnd);

    if (nBeg == nEnd)
    {
        if (VK_BACK == vkCode && nBeg > 0)
        {
            strText = strLeft.Left(nBeg - 1);
            strText += _T("0");
            strText += strRight;
            nBeg--;
            nEnd--;
        }
        else if (VK_DELETE == vkCode && nEnd < strText.GetLength())
        {
            strText = strLeft.Left(nBeg);
            strText += _T("0");

            strRight = strRight.Right(strRight.GetLength() - 1);
            strText += strRight;
            nBeg++;
            nEnd++;
        }
    }
    else
    {
        strText = strLeft.Left(nBeg);

        CString strZero;

        for (int i = nBeg; i < nEnd; i++)
        {
            strText += _T("0");
        }
        strText += strRight;
    }

    SetWindowText(hWndFocus, strText);
    SendMessage(hWndFocus, EM_SETSEL, nBeg, nEnd);

    return TRUE;
}

BOOL OnHexInput(HWND hWndFocus, UINT vkCode)
{
    HWND hWndData8 = GetDlgItem(g_hWnd, IDC_EDIT_DATA8);
    HWND hWndAddr8 = GetDlgItem(g_hWnd, IDC_EDIT_ADDR8);
    HWND hWndAddr16 = GetDlgItem(g_hWnd, IDC_EDIT_ADDR16);
    HWND hWndOffset8 = GetDlgItem(g_hWnd, IDC_EDIT_OFFSET8);

    if (
        hWndFocus != hWndData8 &&
        hWndFocus != hWndAddr8 &&
        hWndFocus != hWndAddr16 &&
        hWndFocus != hWndOffset8
        )
    {
        return FALSE;
    }

    int nMax = 255;
    if (hWndFocus == hWndAddr16)
    {
        nMax = 65535;
    }

    CString strText = GetWindowText(hWndFocus);
    int iStart = 0;
    int iEnd = 0;

    SendMessage(hWndFocus, EM_GETSEL, (WPARAM)&iStart, (LPARAM)&iEnd);

    if ((VK_BACK == vkCode) || (VK_DELETE == vkCode))
    {
        CheckDelData(hWndFocus, vkCode, iStart, iEnd, 16);
        UpdateHexData();
        UpdateDecText();
        UpdateBinText();
        UpdateData(g_hWnd, GetDlgItem(g_hWnd, IDC_COMBO_OP));
        return TRUE;
    }

    if ( !(vkCode >= '0' && vkCode <= '9' || vkCode >= 'A' && vkCode <= 'F') )
    {
        return TRUE;
    }

    if (!CheckPreData(hWndFocus, vkCode, iStart, iEnd, nMax, 16))
    {
        UpdateHexData();
        UpdateDecText();
        UpdateBinText();
        UpdateData(g_hWnd, GetDlgItem(g_hWnd, IDC_COMBO_OP));
    }

    return FALSE;
}

BOOL OnDecInput(HWND hWndFocus, UINT vkCode)
{
    HWND hWndData8 = GetDlgItem(g_hWnd, IDC_EDIT_DATA8_DEC);
    HWND hWndAddr8 = GetDlgItem(g_hWnd, IDC_EDIT_ADDR8_DEC);
    HWND hWndAddr16 = GetDlgItem(g_hWnd, IDC_EDIT_ADDR16_DEC);
    HWND hWndOffset8 = GetDlgItem(g_hWnd, IDC_EDIT_OFFSET8_DEC);

    if (
        hWndFocus != hWndData8 &&
        hWndFocus != hWndAddr8 &&
        hWndFocus != hWndAddr16 &&
        hWndFocus != hWndOffset8
        )
    {
        return FALSE;
    }

    int nMax = 255;
    if (hWndFocus == hWndAddr16)
    {
        nMax = 65535;
    }

    CString strText = GetWindowText(hWndFocus);
    int iStart = 0;
    int iEnd = 0;

    SendMessage(hWndFocus, EM_GETSEL, (WPARAM)&iStart, (LPARAM)&iEnd);

    if ((VK_BACK == vkCode) || (VK_DELETE == vkCode))
    {
        CheckDelData(hWndFocus, vkCode, iStart, iEnd, 10);
        UpdateDecData();
        UpdateHexText();
        UpdateBinText();
        UpdateData(g_hWnd, GetDlgItem(g_hWnd, IDC_COMBO_OP));
        return TRUE;
    }

    if (!(vkCode >= '0' && vkCode <= '9'))
    {
        return TRUE;
    }

    if (!CheckPreData(hWndFocus, vkCode, iStart, iEnd, nMax, 10))
    {
        UpdateDecData();
        UpdateHexText();
        UpdateBinText();
        UpdateData(g_hWnd, GetDlgItem(g_hWnd, IDC_COMBO_OP));
    }

    return FALSE;
}

BOOL OnBinInput(HWND hWndFocus, UINT vkCode)
{
    HWND hWndData8 = GetDlgItem(g_hWnd, IDC_EDIT_DATA8_BIN);
    HWND hWndAddr8 = GetDlgItem(g_hWnd, IDC_EDIT_ADDR8_BIN);
    HWND hWndAddr16 = GetDlgItem(g_hWnd, IDC_EDIT_ADDR16_BIN);
    HWND hWndOffset8 = GetDlgItem(g_hWnd, IDC_EDIT_OFFSET8_BIN);

    if (
        hWndFocus != hWndData8 &&
        hWndFocus != hWndAddr8 &&
        hWndFocus != hWndAddr16 &&
        hWndFocus != hWndOffset8
        )
    {
        return FALSE;
    }

    int nMax = 255;
    if (hWndFocus == hWndAddr16)
    {
        nMax = 65535;
    }

    CString strText = GetWindowText(hWndFocus);
    int iStart = 0;
    int iEnd = 0;

    SendMessage(hWndFocus, EM_GETSEL, (WPARAM)&iStart, (LPARAM)&iEnd);

    if ((VK_BACK == vkCode) || (VK_DELETE == vkCode))
    {
        CheckDelData(hWndFocus, vkCode, iStart, iEnd, 2);
        UpdateBinData();
        UpdateHexText();
        UpdateDecText();
        UpdateData(g_hWnd, GetDlgItem(g_hWnd, IDC_COMBO_OP));
        return TRUE;
    }

    if (!(vkCode >= '0' && vkCode <= '1'))
    {
        return TRUE;
    }

    if (!CheckPreData(hWndFocus, vkCode, iStart, iEnd, nMax, 2))
    {
        UpdateBinData();
        UpdateHexText();
        UpdateDecText();
        UpdateData(g_hWnd, GetDlgItem(g_hWnd, IDC_COMBO_OP));
    }

    return FALSE;
}

LRESULT CALLBACK KeyboardProc(_In_ int code, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
    if (code >= HC_ACTION)
    {
        UINT vkCode = (UINT)wParam;

        HWND hWndFocus = GetFocus();
        HWND hWndFind = GetDlgItem(g_hWnd, IDC_EDIT_FIND);
        SHORT ctrlState = GetAsyncKeyState(VK_CONTROL) & 0x8000;
        WORD keyFlags = HIWORD(lParam);

        if (VK_RETURN == vkCode)
        {
            return CallNextHookEx(g_hKeyHook, code, wParam, lParam);
        }

        if (hWndFind == hWndFocus)
        {
            FindData();
            return CallNextHookEx(g_hKeyHook, code, wParam, lParam);
        }

        if (vkCode >= VK_NUMPAD0 && vkCode <= VK_NUMPAD9)
        {
            vkCode -= 0x30;
        }

        if (VK_TAB == vkCode)
        {
            return CallNextHookEx(g_hKeyHook, code, wParam, lParam);
        }

        if ((ctrlState && 'V') || (ctrlState && 'X'))
        {
            return 1;
        }

        if ((ctrlState && 'Z') == vkCode || (ctrlState && 'A'))
        {
            return CallNextHookEx(g_hKeyHook, code, wParam, lParam);
        }

        if (VK_LEFT == vkCode || VK_RIGHT == vkCode || VK_UP == vkCode || VK_DOWN == vkCode ||
            
            VK_HOME == vkCode || VK_END == vkCode
            )
        {
            return CallNextHookEx(g_hKeyHook, code, wParam, lParam);
        }

        if (keyFlags & KF_UP)
        {
            return 1;
        }

        OnHexInput(hWndFocus, vkCode);
        OnDecInput(hWndFocus, vkCode);
        OnBinInput(hWndFocus, vkCode);

        return 1;
    }

    return CallNextHookEx(g_hKeyHook, code, wParam, lParam);
}
